Pythonμ ast λͺ¨λμ μ¬μ©νμ¬ μΆμ ꡬ문 νΈλ¦¬λ₯Ό μ‘°μνλ λ°©λ²μ μμ보μΈμ. Python μ½λλ₯Ό νλ‘κ·Έλλ° λ°©μμΌλ‘ λΆμ, μμ λ° μμ±νλ λ°©λ²μ λ°°μλλ€.
Python Ast λͺ¨λ: μΆμ ꡬ문 νΈλ¦¬ μ‘°μ μλ²½ ν΄μ€
Python ast
λͺ¨λμ Python μ½λμ μΆμ ꡬ문 νΈλ¦¬(AST)μ μνΈ μμ©ν μ μλ κ°λ ₯ν λ°©λ²μ μ 곡ν©λλ€. ASTλ μμ€ μ½λμ ꡬ문 ꡬ쑰λ₯Ό νΈλ¦¬ ννλ‘ ννν κ²μΌλ‘, Python μ½λλ₯Ό νλ‘κ·Έλλ° λ°©μμΌλ‘ λΆμ, μμ νκ³ μ¬μ§μ΄ μμ±ν μ μκ² ν΄μ€λλ€. μ΄λ₯Ό ν΅ν΄ μ½λ λΆμ λꡬ, μλ 리ν©ν λ§, μ μ λΆμ, μ¬μ©μ μ μ μΈμ΄ νμ₯ λ± λ€μν μ ν리μΌμ΄μ
μ κ°λ°ν μ μμ΅λλ€. μ΄ λ¬Έμμμλ ast
λͺ¨λμ κΈ°λ³Έ μ¬νμ μλ΄νκ³ , μ€μ©μ μΈ μμ μ κ·Έ κΈ°λ₯μ λν ν΅μ°°λ ₯μ μ 곡ν©λλ€.
μΆμ ꡬ문 νΈλ¦¬(AST)λ 무μμ λκΉ?
ast
λͺ¨λμ λν΄ μμΈν μμ보기 μ μ μΆμ ꡬ문 νΈλ¦¬κ° 무μμΈμ§ μ΄ν΄ν΄ λ΄
μλ€. Python μΈν°ν리ν°κ° μ½λλ₯Ό μ€νν λ 첫 λ²μ§Έ λ¨κ³λ μ½λλ₯Ό ASTλ‘ νμ±νλ κ²μ
λλ€. μ΄ νΈλ¦¬ ꡬ쑰λ ν¨μ, ν΄λμ€, 루ν, ννμ, μ°μ°μμ κ°μ μ½λμ ꡬ문 μμμ κ·Έ κ΄κ³λ₯Ό λνλ
λλ€. ASTλ 곡백μ΄λ μ£Όμκ³Ό κ°μ λΆνμν μΈλΆ μ¬νμ λ²λ¦¬κ³ νμμ μΈ κ΅¬μ‘° μ 보μ μ§μ€ν©λλ€. μ΄λ¬ν λ°©μμΌλ‘ μ½λλ₯Ό ννν¨μΌλ‘μ¨ νλ‘κ·Έλ¨μ΄ μ½λ μ체λ₯Ό λΆμνκ³ μ‘°μν μ μκ² λμ΄ λ€μν μν©μμ λ§€μ° μ μ©ν©λλ€.
ast
λͺ¨λ μμνκΈ°
ast
λͺ¨λμ Python νμ€ λΌμ΄λΈλ¬λ¦¬μ μΌλΆμ΄λ―λ‘ μΆκ° ν¨ν€μ§λ₯Ό μ€μΉν νμκ° μμ΅λλ€. μ¬μ©νλ €λ©΄ κ°λ¨ν μν¬νΈνμμμ€:
import ast
ast
λͺ¨λμ ν΅μ¬ κΈ°λ₯μ ast.parse()
μ
λλ€. μ΄ ν¨μλ Python μ½λ λ¬Έμμ΄μ μ
λ ₯μΌλ‘ λ°μ AST κ°μ²΄λ₯Ό λ°νν©λλ€.
code = """
def add(x, y):
return x + y
"""
ast_tree = ast.parse(code)
print(ast_tree)
μ΄κ²μ λ€μκ³Ό κ°μ κ²μ μΆλ ₯ν©λλ€: <_ast.Module object at 0x...>
. μ΄ μΆλ ₯μ νΉλ³ν μ μ΅νμ§λ μμ§λ§ μ½λκ° ASTλ‘ μ±κ³΅μ μΌλ‘ νμ±λμμμ λνλ
λλ€. μ΄μ ast_tree
κ°μ²΄λ νμ±λ μ½λμ μ 체 ꡬ쑰λ₯Ό ν¬ν¨ν©λλ€.
AST νμ
ASTμ ꡬ쑰λ₯Ό μ΄ν΄νκΈ° μν΄ ast.dump()
ν¨μλ₯Ό μ¬μ©ν μ μμ΅λλ€. μ΄ ν¨μλ νΈλ¦¬λ₯Ό μ¬κ·μ μΌλ‘ νμνκ³ κ° λ
Έλμ μμΈν ννμ μΆλ ₯ν©λλ€.
code = """
def add(x, y):
return x + y
"""
ast_tree = ast.parse(code)
print(ast.dump(ast_tree, indent=4))
μΆλ ₯μ λ€μκ³Ό κ°μ΅λλ€:
Module(
body=[
FunctionDef(
name='add',
args=arguments(
posonlyargs=[],
args=[
arg(arg='x', annotation=None, type_comment=None),
arg(arg='y', annotation=None, type_comment=None)
],
kwonlyargs=[],
kw_defaults=[],
defaults=[]
),
body=[
Return(
value=BinOp(
left=Name(id='x', ctx=Load()),
op=Add(),
right=Name(id='y', ctx=Load())
)
)
],
decorator_list=[],
returns=None,
type_comment=None
)
],
type_ignores=[]
)
μ΄ μΆλ ₯μ μ½λμ κ³μΈ΅μ ꡬ쑰λ₯Ό 보μ¬μ€λλ€. μμΈν μ΄ν΄λ³΄κ² μ΅λλ€:
Module
: μ 체 λͺ¨λμ λνλ΄λ λ£¨νΈ λ Έλμ λλ€.body
: λͺ¨λ λ΄μ λͺ λ Ήλ¬Έ λͺ©λ‘μ λλ€.FunctionDef
: ν¨μ μ μλ₯Ό λνλ λλ€. κ·Έ μμ±μ λ€μκ³Ό κ°μ΅λλ€:name
: ν¨μ μ΄λ¦('add').args
: ν¨μμ μΈμ.arguments
: ν¨μμ μΈμμ λν μ 보λ₯Ό ν¬ν¨ν©λλ€.arg
: λ¨μΌ μΈμ(μ: 'x', 'y')λ₯Ό λνλ λλ€.body
: ν¨μ λ³Έλ¬Έ(λͺ λ Ήλ¬Έ λͺ©λ‘).Return
: return λ¬Έμ λνλ λλ€.value
: λ°νλλ κ°.BinOp
: μ΄ν μ°μ°(μ: x + y)μ λνλ λλ€.left
: μΌμͺ½ νΌμ°μ°μ(μ: 'x').op
: μ°μ°μ(μ: 'Add').right
: μ€λ₯Έμͺ½ νΌμ°μ°μ(μ: 'y').
AST νμ
ast
λͺ¨λμ ASTλ₯Ό νμνκΈ° μν΄ ast.NodeVisitor
ν΄λμ€λ₯Ό μ 곡ν©λλ€. ast.NodeVisitor
λ₯Ό μλΈν΄λμ±νκ³ κ·Έ λ©μλλ₯Ό μ€λ²λΌμ΄λν¨μΌλ‘μ¨ νμ μ€μ νΉμ λ
Έλ μ νμ μ²λ¦¬ν μ μμ΅λλ€. μ΄κ²μ μ½λ ꡬ쑰λ₯Ό λΆμνκ±°λ, νΉμ ν¨ν΄μ μλ³νκ±°λ, μ 보λ₯Ό μΆμΆνλ λ° μ μ©ν©λλ€.
import ast
class FunctionNameExtractor(ast.NodeVisitor):
def __init__(self):
self.function_names = []
def visit_FunctionDef(self, node):
self.function_names.append(node.name)
code = """
def add(x, y):
return x + y
def subtract(x, y):
return x - y
"""
ast_tree = ast.parse(code)
extractor = FunctionNameExtractor()
extractor.visit(ast_tree)
print(extractor.function_names) # Output: ['add', 'subtract']
μ΄ μμ μμ FunctionNameExtractor
λ ast.NodeVisitor
μμ μμλ°κ³ visit_FunctionDef
λ©μλλ₯Ό μ€λ²λΌμ΄λν©λλ€. μ΄ λ©μλλ ASTμ κ° ν¨μ μ μ λ
Έλμ λν΄ νΈμΆλ©λλ€. μ΄ λ©μλλ ν¨μ μ΄λ¦μ function_names
λͺ©λ‘μ μΆκ°ν©λλ€. visit()
λ©μλλ AST νμμ μμν©λλ€.
μμ : λͺ¨λ λ³μ ν λΉ μ°ΎκΈ°
import ast
class VariableAssignmentFinder(ast.NodeVisitor):
def __init__(self):
self.assignments = []
def visit_Assign(self, node):
for target in node.targets:
if isinstance(target, ast.Name):
self.assignments.append(target.id)
code = """
x = 10
y = x + 5
message = "hello"
"""
ast_tree = ast.parse(code)
finder = VariableAssignmentFinder()
finder.visit(ast_tree)
print(finder.assignments) # Output: ['x', 'y', 'message']
μ΄ μμ λ μ½λμμ λͺ¨λ λ³μ ν λΉμ μ°Ύμ΅λλ€. visit_Assign
λ©μλλ κ° ν λΉ λͺ
λ Ήλ¬Έμ λν΄ νΈμΆλ©λλ€. μ΄ λ©μλλ ν λΉμ λμμ λ°λ³΅νκ³ , λμμ΄ λ¨μ μ΄λ¦(ast.Name
)μΈ κ²½μ° μ΄λ¦μ assignments
λͺ©λ‘μ μΆκ°ν©λλ€.
AST μμ
ast
λͺ¨λμ ASTλ₯Ό μμ ν μλ μμ΅λλ€. κΈ°μ‘΄ λ
Έλλ₯Ό λ³κ²½νκ±°λ, μ λ
Έλλ₯Ό μΆκ°νκ±°λ, λ
Έλλ₯Ό μμ ν μ κ±°ν μ μμ΅λλ€. ASTλ₯Ό μμ νλ €λ©΄ ast.NodeTransformer
ν΄λμ€λ₯Ό μ¬μ©ν©λλ€. ast.NodeVisitor
μ μ μ¬νκ² ast.NodeTransformer
λ₯Ό μλΈν΄λμ±νκ³ κ·Έ λ©μλλ₯Ό μ€λ²λΌμ΄λνμ¬ νΉμ λ
Έλ μ νμ μμ ν©λλ€. μ£Όμ μ°¨μ΄μ μ ast.NodeTransformer
λ©μλλ μμ λ λ
Έλ(λλ λ체ν μ λ
Έλ)λ₯Ό λ°νν΄μΌ νλ€λ κ²μ
λλ€. λ©μλκ° None
μ λ°ννλ©΄ λ
Έλλ ASTμμ μ κ±°λ©λλ€.
ASTλ₯Ό μμ ν νμλ compile()
ν¨μλ₯Ό μ¬μ©νμ¬ λ€μ μ€ν κ°λ₯ν Python μ½λλ‘ μ»΄νμΌν΄μΌ ν©λλ€.
import ast
class AddOneTransformer(ast.NodeTransformer):
def visit_Num(self, node):
return ast.Num(n=node.n + 1)
code = """
x = 10
y = 20
"""
ast_tree = ast.parse(code)
transformer = AddOneTransformer()
new_ast_tree = transformer.visit(ast_tree)
new_code = compile(new_ast_tree, '', 'exec')
# Execute the modified code
exec(new_code)
print(x) # Output: 11
print(y) # Output: 21
μ΄ μμ μμ AddOneTransformer
λ ast.NodeTransformer
μμ μμλ°κ³ visit_Num
λ©μλλ₯Ό μ€λ²λΌμ΄λν©λλ€. μ΄ λ©μλλ κ° μ«μ 리ν°λ΄ λ
Έλ(ast.Num
)μ λν΄ νΈμΆλ©λλ€. μ΄ λ©μλλ κ°μ 1μ© μ¦κ°μν¨ μ ast.Num
λ
Έλλ₯Ό λ§λλλ€. visit()
λ©μλλ μμ λ ASTλ₯Ό λ°νν©λλ€.
compile()
ν¨μλ μμ λ AST, νμΌ μ΄λ¦(μ΄ κ²½μ° <string>
μ μ½λκ° λ¬Έμμ΄μμ μ¨ κ²μμ λνλ) λ° μ€ν λͺ¨λ(μ½λ λΈλ‘μ μ€ννκΈ° μν 'exec'
)λ₯Ό μ¬μ©ν©λλ€. μ΄λ exec()
ν¨μλ₯Ό μ¬μ©νμ¬ μ€νν μ μλ μ½λ κ°μ²΄λ₯Ό λ°νν©λλ€.
μμ : λ³μ μ΄λ¦ λ°κΎΈκΈ°
import ast
class VariableNameReplacer(ast.NodeTransformer):
def __init__(self, old_name, new_name):
self.old_name = old_name
self.new_name = new_name
def visit_Name(self, node):
if node.id == self.old_name:
return ast.Name(id=self.new_name, ctx=node.ctx)
return node
code = """
def multiply_by_two(number):
return number * 2
result = multiply_by_two(5)
print(result)
"""
ast_tree = ast.parse(code)
replacer = VariableNameReplacer('number', 'num')
new_ast_tree = replacer.visit(ast_tree)
new_code = compile(new_ast_tree, '', 'exec')
# Execute the modified code
exec(new_code)
μ΄ μμ λ λ³μ μ΄λ¦ 'number'
μ λͺ¨λ μΈμ€ν΄μ€λ₯Ό 'num'
μΌλ‘ λ°κΏλλ€. VariableNameReplacer
λ μ΄μ μ΄λ¦κ³Ό μ μ΄λ¦μ μΈμλ‘ μ¬μ©ν©λλ€. visit_Name
λ©μλλ κ° μ΄λ¦ λ
Έλμ λν΄ νΈμΆλ©λλ€. λ
Έλμ μλ³μκ° μ΄μ μ΄λ¦κ³Ό μΌμΉνλ©΄ μ μ΄λ¦κ³Ό λμΌν 컨ν
μ€νΈ(node.ctx
)λ‘ μ ast.Name
λ
Έλλ₯Ό λ§λλλ€. 컨ν
μ€νΈλ μ΄λ¦μ΄ μ¬μ©λλ λ°©μ(μ: λ‘λ, μ μ₯)μ λνλ
λλ€.
ASTμμ μ½λ μμ±
compile()
μ μ¬μ©νλ©΄ ASTμμ μ½λλ₯Ό μ€νν μ μμ§λ§ μ½λλ₯Ό λ¬Έμμ΄λ‘ κ°μ Έμ€λ λ°©λ²μ μ 곡νμ§ μμ΅λλ€. ASTμμ Python μ½λλ₯Ό μμ±νλ €λ©΄ astunparse
λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©ν μ μμ΅λλ€. μ΄ λΌμ΄λΈλ¬λ¦¬λ νμ€ λΌμ΄λΈλ¬λ¦¬μ μΌλΆκ° μλλ―λ‘ λ¨Όμ μ€μΉν΄μΌ ν©λλ€:
pip install astunparse
κ·Έλ° λ€μ astunparse.unparse()
ν¨μλ₯Ό μ¬μ©νμ¬ ASTμμ μ½λλ₯Ό μμ±ν μ μμ΅λλ€.
import ast
import astunparse
code = """
def add(x, y):
return x + y
"""
ast_tree = ast.parse(code)
generated_code = astunparse.unparse(ast_tree)
print(generated_code)
μΆλ ₯μ λ€μκ³Ό κ°μ΅λλ€:
def add(x, y):
return (x + y)
μ°Έκ³ : (x + y)
μ£Όμμ κ΄νΈλ μ¬λ°λ₯Έ μ°μ°μ μ°μ μμλ₯Ό 보μ₯νκΈ° μν΄ astunparse
μμ μΆκ°λ©λλ€. μ΄λ¬ν κ΄νΈλ μ격νκ² νμνμ§ μμ μ μμ§λ§ μ½λμ μ νμ±μ 보μ₯ν©λλ€.
μμ : κ°λ¨ν ν΄λμ€ μμ±
import ast
import astunparse
class_name = 'MyClass'
method_name = 'my_method'
# Create the class definition node
class_def = ast.ClassDef(
name=class_name,
bases=[],
keywords=[],
body=[
ast.FunctionDef(
name=method_name,
args=ast.arguments(
posonlyargs=[],
args=[],
kwonlyargs=[],
kw_defaults=[],
defaults=[]
),
body=[
ast.Pass()
],
decorator_list=[],
returns=None,
type_comment=None
)
],
decorator_list=[]
)
# Create the module node containing the class definition
module = ast.Module(body=[class_def], type_ignores=[])
# Generate the code
code = astunparse.unparse(module)
print(code)
μ΄ μμ λ λ€μ Python μ½λλ₯Ό μμ±ν©λλ€:
class MyClass:
def my_method():
pass
μ΄κ²μ μ²μλΆν° ASTλ₯Ό λΉλν λ€μ κ±°κΈ°μμ μ½λλ₯Ό μμ±νλ λ°©λ²μ 보μ¬μ€λλ€. μ΄ μ κ·Ό λ°©μμ μ½λ μμ± λꡬ λ° λ©ν νλ‘κ·Έλλ°μ κ°λ ₯ν©λλ€.
ast
λͺ¨λμ μ€μ μμ© νλ‘κ·Έλ¨
ast
λͺ¨λμλ λ€μκ³Ό κ°μ λ€μν μ€μ μμ© νλ‘κ·Έλ¨μ΄ μμ΅λλ€:
- μ½λ λΆμ: μ€νμΌ μλ°, 보μ μ·¨μ½μ λλ μ±λ₯ λ³λͺ© νμμ λν μ½λ λΆμ. μλ₯Ό λ€μ΄ λκ·λͺ¨ νλ‘μ νΈμμ μ½λ© νμ€μ μννλ λꡬλ₯Ό μμ±ν μ μμ΅λλ€.
- μλνλ 리ν©ν λ§: λ³μ μ΄λ¦ λ°κΎΈκΈ°, λ©μλ μΆμΆ λλ μ½λλ₯Ό λ³ννμ¬ μ΅μ μΈμ΄ κΈ°λ₯μ μ¬μ©νλ λ±μ μμ
μ μλνν©λλ€.
rope
μ κ°μ λꡬλ κ°λ ₯ν 리ν©ν λ§ κΈ°λ₯μ μν΄ ASTλ₯Ό νμ©ν©λλ€. - μ μ λΆμ: μ€μ λ‘ μ€ννμ§ μκ³ λ μ½λμμ μ μ¬μ μΈ μ€λ₯ λλ λ²κ·Έλ₯Ό μλ³ν©λλ€.
pylint
λ°flake8
κ³Ό κ°μ λꡬλ AST λΆμμ μ¬μ©νμ¬ λ¬Έμ λ₯Ό κ°μ§ν©λλ€. - μ½λ μμ±: ν νλ¦Ώ λλ μ¬μμ λ°λΌ μ½λλ₯Ό μλμΌλ‘ μμ±ν©λλ€. μ΄κ²μ λ°λ³΅μ μΈ μ½λλ₯Ό λ§λ€κ±°λ λ€λ₯Έ νλ«νΌμ λν μ½λλ₯Ό μμ±νλ λ° μ μ©ν©λλ€.
- μΈμ΄ νμ₯: Python μ½λλ₯Ό λ€λ₯Έ ννμΌλ‘ λ³ννμ¬ μ¬μ©μ μ μ μΈμ΄ νμ₯ λλ λλ©μΈ νΉμ μΈμ΄(DSL)λ₯Ό λ§λλλ€.
- 보μ κ°μ¬: μ μ¬μ μΌλ‘ μ ν΄ν ꡬ쑰 λλ μ·¨μ½μ μ λν μ½λ λΆμ. μ΄κ²μ μμ νμ§ μμ μ½λ© μ¬λ‘λ₯Ό μλ³νλ λ° μ¬μ©ν μ μμ΅λλ€.
μμ : μ½λ© μ€νμΌ μ μ©
νλ‘μ νΈμ λͺ¨λ ν¨μ μ΄λ¦μ΄ snake_case κ·μΉ(μ: my_function
λμ myFunction
)μ λ°λ₯΄λλ‘ νκ³ μΆλ€κ³ κ°μ ν΄ λ³΄κ² μ΅λλ€. ast
λͺ¨λμ μ¬μ©νμ¬ μλ° μ¬λΆλ₯Ό νμΈν μ μμ΅λλ€.
import ast
import re
class SnakeCaseChecker(ast.NodeVisitor):
def __init__(self):
self.errors = []
def visit_FunctionDef(self, node):
if not re.match(r'^[a-z]+(_[a-z]+)*$', node.name):
self.errors.append(f"Function name '{node.name}' does not follow snake_case convention")
def check_code(self, code):
ast_tree = ast.parse(code)
self.visit(ast_tree)
return self.errors
# Example usage
code = """
def myFunction(x):
return x * 2
def calculate_area(width, height):
return width * height
"""
checker = SnakeCaseChecker()
errors = checker.check_code(code)
if errors:
for error in errors:
print(error)
else:
print("No style violations found")
μ΄ μ½λλ ast.NodeVisitor
μμ μμλ°λ SnakeCaseChecker
ν΄λμ€λ₯Ό μ μν©λλ€. visit_FunctionDef
λ©μλλ ν¨μ μ΄λ¦μ΄ snake_case μ κ·μκ³Ό μΌμΉνλμ§ νμΈν©λλ€. κ·Έλ μ§ μμΌλ©΄ μ€λ₯ λ©μμ§λ₯Ό errors
λͺ©λ‘μ μΆκ°ν©λλ€. check_code
λ©μλλ μ½λλ₯Ό νμ±νκ³ ASTλ₯Ό νμνλ©° μ€λ₯ λͺ©λ‘μ λ°νν©λλ€.
ast
λͺ¨λλ‘ μμ
ν λμ λͺ¨λ² μ¬λ‘
- AST ꡬ쑰 μ΄ν΄: ASTλ₯Ό μ‘°μνκΈ° μ μ
ast.dump()
λ₯Ό μ¬μ©νμ¬ ν΄λΉ ꡬ쑰λ₯Ό μ΄ν΄νλ λ° μκ°μ ν¬μνμμμ€. μ΄λ κ² νλ©΄ μμ ν΄μΌ ν λ Έλλ₯Ό μλ³νλ λ° λμμ΄ λ©λλ€. ast.NodeVisitor
λ°ast.NodeTransformer
μ¬μ©: μ΄ ν΄λμ€λ νΈλ¦¬λ₯Ό μλμΌλ‘ νμνμ§ μκ³ λ ASTλ₯Ό νμνκ³ μμ νλ νΈλ¦¬ν λ°©λ²μ μ 곡ν©λλ€.- μ² μ ν ν μ€νΈ: ASTλ₯Ό μμ ν λ λ³κ²½ μ¬νμ΄ μ¬λ°λ₯Έμ§ νμΈνκ³ μ€λ₯λ₯Ό μΌμΌν€μ§ μλλ‘ μ½λλ₯Ό μ² μ ν ν μ€νΈνμμμ€.
- μ½λ μμ±μ
astunparse
κ³ λ €:compile()
μ μμ λ μ½λλ₯Ό μ€ννλ λ° μ μ©νμ§λ§astunparse
λ ASTμμ μ½μ μ μλ Python μ½λλ₯Ό μμ±νλ λ°©λ²μ μ 곡ν©λλ€. - μ ν ννΈ μ¬μ©: μ ν ννΈλ νΉν 볡μ‘ν AST κ΅¬μ‘°λ‘ μμ ν λ μ½λμ κ°λ μ±κ³Ό μ μ§ κ΄λ¦¬μ±μ ν¬κ² ν₯μμν¬ μ μμ΅λλ€.
- μ½λ λ¬Έμν: μ¬μ©μ μ μ AST λ°©λ¬Έμ λλ λ³νκΈ°λ₯Ό λ§λ€ λ κ° λ©μλμ λͺ©μ κ³Ό ASTμ λν λ³κ²½ μ¬νμ μ€λͺ νκΈ° μν΄ μ½λλ₯Ό λͺ ννκ² λ¬Έμννμμμ€.
κ³Όμ λ° κ³ λ € μ¬ν
- 볡μ‘μ±: ASTλ‘ μμ νλ κ²μ νΉν λ ν° μ½λλ² μ΄μ€μ κ²½μ° λ³΅μ‘ν μ μμ΅λλ€. λ€μν λ Έλ μ νκ³Ό κ·Έ κ΄κ³λ₯Ό μ΄ν΄νλ κ²μ μ΄λ €μΈ μ μμ΅λλ€.
- μ μ§ κ΄λ¦¬: AST ꡬ쑰λ Python λ²μ κ°μ λ³κ²½λ μ μμ΅λλ€. νΈνμ±μ 보μ₯νλ €λ©΄ λ€λ₯Έ Python λ²μ μΌλ‘ μ½λλ₯Ό ν μ€νΈνμμμ€.
- μ±λ₯: λκ·λͺ¨ ASTλ₯Ό νμνκ³ μμ νλ λ° μκ°μ΄ μ€λ 걸릴 μ μμ΅λλ€. μ±λ₯μ ν₯μμν€κΈ° μν΄ μ½λλ₯Ό μ΅μ ννλ κ²μ κ³ λ €νμμμ€. μμ£Ό μ‘μΈμ€νλ λ Έλλ₯Ό μΊμ±νκ±°λ λ ν¨μ¨μ μΈ μκ³ λ¦¬μ¦μ μ¬μ©νλ©΄ λμμ΄ λ μ μμ΅λλ€.
- μ€λ₯ μ²λ¦¬: ASTλ₯Ό νμ±νκ±°λ μ‘°μν λ μ€λ₯λ₯Ό μ μμ μΌλ‘ μ²λ¦¬νμμμ€. μ¬μ©μμκ² μ μ΅ν μ€λ₯ λ©μμ§λ₯Ό μ 곡νμμμ€.
- 보μ: νΉν ASTκ° μ¬μ©μ μ λ ₯μ κΈ°λ°μΌλ‘ νλ κ²½μ° ASTμμ μμ±λ μ½λλ₯Ό μ€νν λ μ£Όμνμμμ€. μ½λ μ½μ 곡격μ λ°©μ§νκΈ° μν΄ μ λ ₯μ μμ νμμμ€.
κ²°λ‘
Python ast
λͺ¨λμ Python μ½λμ μΆμ ꡬ문 νΈλ¦¬μ μνΈ μμ©ν μ μλ κ°λ ₯νκ³ μ μ°ν λ°©λ²μ μ 곡ν©λλ€. AST ꡬ쑰λ₯Ό μ΄ν΄νκ³ ast.NodeVisitor
λ° ast.NodeTransformer
ν΄λμ€λ₯Ό μ¬μ©νλ©΄ Python μ½λλ₯Ό νλ‘κ·Έλλ° λ°©μμΌλ‘ λΆμ, μμ λ° μμ±ν μ μμ΅λλ€. μ΄κ²μ μ½λ λΆμ λꡬμμ μλ 리ν©ν λ§, μ¬μ©μ μ μ μΈμ΄ νμ₯μ μ΄λ₯΄κΈ°κΉμ§ κ΄λ²μν μμ© νλ‘κ·Έλ¨μ μν λ¬Έμ μ½λλ€. ASTλ‘ μμ
νλ κ²μ΄ 볡μ‘ν μ μμ§λ§ μ½λλ₯Ό νλ‘κ·Έλλ° λ°©μμΌλ‘ μ‘°μν μ μλ€λ μ΄μ μ μλΉν©λλ€. ast
λͺ¨λμ νμ λ°μλ€μ¬ Python νλ‘μ νΈμμ μλ‘μ΄ κ°λ₯μ±μ μ΄μ΄λ³΄μμμ€.